import { ref } from 'vue';
import axios, { AxiosError, AxiosHeaders, AxiosInstance, InternalAxiosRequestConfig } from 'axios';

// 类型声明扩展
declare module 'axios' {
    interface AxiosRequestConfig {
        _retried?: boolean;
    }
}

/** 认证状态接口 */
interface AuthStore {
    token: string | null;
    refreshToken: string | null;
    expiresAt: number | null;
}

/** 全局配置常量 */
const CONFIG = {
    BASE_URL: '/api',
    TIMEOUT: 10000,
    TOKEN_BUFFER: 30000 // 过期前30秒刷新
};

/** 认证状态存储 */
const authStore = ref<AuthStore>({
    token: null,
    refreshToken: localStorage.getItem('refreshToken'),
    expiresAt: Number(localStorage.getItem('tokenExpiresAt')) || null
});

/** 创建认证API实例 */
const createAuthClient = (): AxiosInstance => {
    const client = axios.create({
        baseURL: CONFIG.BASE_URL,
        timeout: CONFIG.TIMEOUT
    });

    // 请求拦截器
    client.interceptors.request.use(async (config: InternalAxiosRequestConfig) => {
        config.headers = config.headers || {} as AxiosHeaders;
        (config.headers as AxiosHeaders).set('Authorization', `Bearer ${await getValidToken() || 'noToken'}`);

        console.log({
            'Request URL': config.url,
            'Request Headers': config.headers,
            'Request Method': config.method,
            'Request Data': config.data,
        });
        return config;
    });

    // 响应拦截器
    client.interceptors.response.use(
        res => res,
        (err: AxiosError) => handleAuthError(err, client)
    );

    return client;
};

/** Token有效性检查 */
const isValidToken = (): boolean => {
    const { token, expiresAt } = authStore.value;
    return !!token && !!expiresAt && Date.now() < expiresAt - CONFIG.TOKEN_BUFFER;
};

/** 持久化存储方法 */
const persistAuth = (): void => {
    localStorage.setItem('refreshToken', authStore.value.refreshToken || '');
    localStorage.setItem('tokenExpiresAt', (authStore.value.expiresAt || 0).toString());
};

/** 更新认证状态 */
interface UpdateAuthParams {
    accessToken: string;
    refreshToken: string;
    expiresIn: number;
}

const updateAuth = ({ accessToken, refreshToken, expiresIn }: UpdateAuthParams): void => {
    authStore.value = {
        token: accessToken,
        refreshToken: refreshToken,
        expiresAt: Date.now() + expiresIn * 1000
    };
    persistAuth();
};

/** 清除认证信息 */
const clearAuth = (): void => {
    authStore.value = { token: null, refreshToken: null, expiresAt: null };
    localStorage.removeItem('refreshToken');
    localStorage.removeItem('tokenExpiresAt');
    console.log("清除认证信息!");
};

/** Token刷新控制 */
let refreshTask: Promise<string> | null = null;
const refreshToken = async (): Promise<string> => {
    try {
        const { data } = await axios.post<UpdateAuthParams>(
            `${CONFIG.BASE_URL}/user/refresh-token`,
            {},
            {
                headers: {
                    Authorization: `Bearer ${authStore.value.refreshToken}`
                }
            }
        );
        updateAuth(data);
        console.log("Token刷新成功：", data.accessToken);
        return data.accessToken;
    } catch (error) {
        clearAuth();
        console.error("Token刷新失败：", error);
        throw new Error('REFRESH_FAILED');
    }
};

/** 获取有效Token */
const getValidToken = async (): Promise<string> => {
    if (!authStore.value.refreshToken)
        return null;
    console.log("获取refreshToken：", authStore.value.refreshToken);
    if (isValidToken()) return authStore.value.token;
    if (!refreshTask) {
        refreshTask = refreshToken().finally(() => refreshTask = null);
    }
    return refreshTask;
};

/** 处理认证错误 */
const handleAuthError = async (
    error: AxiosError,
    client: AxiosInstance
): Promise<unknown> => {
    const req = error.config;

    if (error.response?.status === 401 && !req?._retried) {
        req._retried = true;

        try {
            req.headers = (req.headers || new AxiosHeaders()) as AxiosHeaders;
            req.headers.Authorization = `Bearer ${await refreshToken()}`;
            return client(req);
        } catch (error) {
            clearAuth();
            console.error("认证错误：", error);
            window.location.replace('/login');
        }
    }

    return Promise.reject(error);
};

// 初始化实例并导出
const tokenAxios = createAuthClient();
export { tokenAxios, getValidToken, updateAuth, clearAuth, UpdateAuthParams };